home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 July / EnigmA AMIGA RUN 09 (1996)(G.R. Edizioni)(IT)[!][issue 1996-07 & 08][EARSAN CD VIII].iso / earcd / dev1 / vbcc.lha / vbcc / opt.c < prev    next >
C/C++ Source or Header  |  1996-05-15  |  21KB  |  497 lines

  1. /*  $VER: vbcc (opt.c) V0.3     */
  2. /*  allgemeine Routinen fuer den Optimizer und Steuerung der einzelnen  */
  3. /*  Laeufe                                                              */
  4.  
  5. #include "opt.h"
  6.  
  7. /*  die naechsten Funktionen sollten evtl. in ic.c                  */
  8.  
  9. void insert_IC(struct IC *p,struct IC *new)
  10. /*  fuegt new hinter p ein; p darf 0 sein                           */
  11. {
  12.     new->prev=p;
  13.     if(p){ new->next=p->next; p->next=new; }
  14.      else{ new->next=first_ic; first_ic=new; }
  15.     if(new->next) new->next->prev=new; else last_ic=new;
  16.     new->q1.am=new->q2.am=new->z.am=0;
  17. }
  18.  
  19.  
  20. #ifndef NO_OPTIMIZER
  21.  
  22. int gchanged;   /*  Merker, ob Optimierungslauf etwas geaendert hat */
  23. int norek;      /*  diese Funktion wird nicht rekursiv auf          */
  24. int nocall;     /*  diese Funktion kehrt nicht zum Caller zurueck   */
  25.  
  26. /*  temporary fuer verschiedene Bitvektoren */
  27. unsigned char *tmp;
  28.  
  29. void recalc_offsets(struct flowgraph *fg)
  30. /*  berechnet Offsets fuer auto-Variablen neu und versucht, fuer Variablen, */
  31. /*  die nicht gleichzeitig aktiv sind, den gleichen Platz zu belegen        */
  32. {
  33.     int i,b,*al,*sz,*eqto;size_t bsize;
  34.     unsigned char **used,*tmp,*empty;
  35.     struct IC *p;
  36.     if(DEBUG&1024) printf("recalculating offsets\n");
  37.     if(DEBUG&1024) printf("setting up arrays\n");
  38.     bsize=(basic_blocks+CHAR_BIT-1)/CHAR_BIT;
  39.     if(DEBUG&1024) printf("bsize=%d\n",bsize);
  40.     tmp=mymalloc(bsize);
  41.     al=mymalloc(sizeof(int)*(vcount-rcount));
  42.     eqto=mymalloc(sizeof(int)*(vcount-rcount));
  43.     sz=mymalloc(sizeof(int)*(vcount-rcount));
  44.     empty=mymalloc(bsize);
  45.     memset(empty,0,bsize);
  46.     used=mymalloc(sizeof(unsigned char *)*(vcount-rcount));
  47.     /*  Tabelle, welche Variable in welchem Block belegt ist, aufbauen  */
  48.     for(i=0;i<vcount-rcount;i++){
  49.         if(vilist[i]->offset>=0&&(vilist[i]->storage_class==AUTO||vilist[i]->storage_class==REGISTER)){
  50.             if(DEBUG&2048) printf("setting up for %s,%d\n",vilist[i]->identifier,vilist[i]->offset);
  51.             used[i]=mymalloc(bsize);
  52.             memset(used[i],0,bsize);
  53.         }else{
  54.             used[i]=0;
  55.         }
  56.         sz[i]=szof(vilist[i]->vtyp);
  57.         al[i]=align[vilist[i]->vtyp->flags&15];
  58.         eqto[i]=-1;
  59.     }
  60.     b=0;
  61.     while(fg){
  62.         if(b>=basic_blocks) ierror(0);
  63.         for(i=0;i<vcount-rcount;i++){
  64.             if(used[i]&&(BTST(fg->av_in,i)||BTST(fg->av_out,i))){
  65.                 int r;
  66.                 BSET(used[i],b);
  67.                 for(r=1;r<=MAXR;r++)
  68.                     if(fg->regv[r]&&fg->regv[r]->index==i) BCLR(used[i],b);
  69.             }
  70.         }
  71.         for(p=fg->start;p;p=p->next){
  72.             if((p->q1.flags&(VAR|REG))==VAR){
  73.                 i=p->q1.v->index;
  74.                 if(used[i]){
  75.                     BSET(used[i],b);
  76.                 }
  77.             }
  78.             if((p->q2.flags&(VAR|REG))==VAR){
  79.                 i=p->q2.v->index;
  80.                 if(used[i]){
  81.                     BSET(used[i],b);
  82.                 }
  83.             }
  84.             if((p->z.flags&(VAR|REG))==VAR){
  85.                 i=p->z.v->index;
  86.                 if(used[i]){
  87.                     BSET(used[i],b);
  88.                 }
  89.             }
  90.             if(p==fg->end) break;
  91.         }
  92.         fg=fg->normalout;
  93.         b++;
  94.     }
  95.     /*  schauen, ob Variablen in gleichen Speicher koennen  */
  96.     if(DEBUG&1024) printf("looking for distinct variables\n");
  97.     for(i=0;i<vcount-rcount;i++){
  98.         if(!used[i]||eqto[i]>=0) continue;
  99.         for(b=i+1;b<vcount-rcount;b++){
  100.             if(!used[b]||eqto[b]>=0) continue;
  101.             if(DEBUG&2048) printf("comparing %s(%d) and %s(%d)\n",vilist[i]->identifier,vilist[i]->offset,vilist[b]->identifier,vilist[b]->offset);
  102.  
  103.             memcpy(tmp,used[i],bsize);
  104.             bvintersect(tmp,used[b],bsize);
  105.             if(!memcmp(tmp,empty,bsize)){
  106.                 if(DEBUG&1024) printf("memory for %s(%d) and %s(%d) equal\n",vilist[i]->identifier,vilist[i]->offset,vilist[b]->identifier,vilist[b]->offset);
  107.                 eqto[b]=i;
  108.                 if(al[b]>al[i]) al[i]=al[b];
  109.                 if(sz[b]>sz[i]) sz[i]=sz[b];
  110.                 bvunite(used[i],used[b],bsize);
  111.             }
  112.         }
  113.     }
  114.     if(DEBUG&1024) printf("final recalculating\n");
  115.     max_offset=0;
  116.     for(i=0;i<vcount-rcount;i++){
  117.         if(!used[i]) continue;
  118.         free(used[i]);
  119.         if(DEBUG&2048) printf("adjusting offset for %s,%d\n",vilist[i]->identifier,vilist[i]->offset);
  120.         if(eqto[i]>=0){
  121.             vilist[i]->offset=vilist[eqto[i]]->offset;
  122.             continue;
  123.         }
  124.         vilist[i]->offset=((max_offset+al[i]-1)/al[i])*al[i];
  125.         max_offset=vilist[i]->offset+sz[i];
  126.     }
  127.     free(used);
  128.     free(sz);
  129.     free(al);
  130.     free(tmp);
  131.     free(empty);
  132.     free(eqto);
  133. }
  134. void remove_IC_fg(struct flowgraph *g,struct IC *p)
  135. /*  entfernt IC p und beachtet Flussgraph   */
  136. {
  137.     if(p->q1.am||p->q2.am||p->z.am) ierror(0);
  138.     if(g->start==g->end){
  139.         g->start=g->end=0;
  140.     }else{
  141.         if(p==g->end) g->end=p->prev;
  142.         if(p==g->start) g->start=p->next;
  143.     }
  144.     remove_IC(p);
  145. }
  146.  
  147. int peephole(void)
  148. /*  macht alle moeglichen Vereinfachungen/Vereinheitlichungen   */
  149. {
  150.     struct IC *p;struct obj o;int t,c,null,eins,changed,done=0;
  151.     do{
  152.         if(DEBUG&1024) printf("searching for peephole optimizations\n");
  153.         changed=0;ic_count=0;
  154.         p=first_ic;
  155.         while(p){
  156.             c=p->code;
  157.             t=p->typf;
  158.             ic_count++;
  159.             if(p->q1.flags&KONST){
  160.                 if((p->q2.flags&KONST)||!p->q2.flags){
  161.                     struct IC *old=p->prev;
  162.                     if(fold(p)){ changed=1; p=old;continue;}
  163.                     p=p->next;continue;
  164.                 }else{
  165.                     if(c==ADD||c==MULT||(c>=OR&&c<=AND)){ /*  const nach rechts   */
  166.                         if(DEBUG&1024){ printf("swapped commutative op:\n");pric2(stdout,p);}
  167.                         o=p->q1;p->q1=p->q2;p->q2=o;
  168.                     }
  169.                 }
  170.             }
  171.             if(p->q2.flags&KONST){
  172.             /*  algebraische Optimierungen  */
  173.                 eval_const(&p->q2.val,t);
  174.                 if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)) null=1; else null=0;
  175.                 if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))) eins=1; else eins=0;
  176.                 if(zleqto(vlong,l2zl(-1L))&&zdeqto(vdouble,d2zd(-1.0))) eins=-1;
  177.                 if(eins<0&&(c==MULT||c==DIV)){
  178.                     if(DEBUG&1024){ printf("MULT/DIV with (-1) converted to MINUS:\n");pric2(stdout,p);}
  179.                     p->code=MINUS;p->q2.flags=0;
  180.                     changed=1;
  181.                 }
  182. #if 0
  183.                 if(c==SUB){
  184.                 /*  VORSICHT: Das funktioniert bei bestimmten Werten nicht! */
  185.                     if(DEBUG&1024){ printf("SUB converted to ADD:\n");pric2(stdout,p);}
  186.                     p->code=ADD; calc(MINUS,t,&p->q2.val,0,&p->q2.val);
  187.                     changed=1;
  188.                 }
  189. #endif
  190.                 if((eins>0&&(c==MULT||c==DIV))||(null&&(c==ADD||c==SUB||c==ADDI2P||c==LSHIFT||c==RSHIFT||c==OR||c==XOR))){
  191.                     if(DEBUG&1024){ printf("operation converted to simple assignment:\n");pric2(stdout,p);}
  192.                     p->code=ASSIGN;p->q2.flags=0;p->q2.reg=sizetab[t&15];
  193.                     changed=1;
  194.                 }
  195.                 if(null&&(c==MULT||c==DIV||c==MOD||c==AND)){
  196.                     if(c==DIV||c==MOD) error(84);
  197.                     if(DEBUG&1024){ printf("operation converted to ASSIGN 0:\n");pric2(stdout,p);}
  198.                     o.val.vlong=l2zl(0L);eval_const(&o.val,LONG);
  199.                     insert_const2(&p->q1.val,t);p->q1.flags=KONST;
  200.                     p->code=ASSIGN;p->q2.flags=0;p->q2.reg=sizetab[t&15];
  201.                     changed=1;
  202.                 }
  203.                 if((t&15)<=LONG&&(c==ADD||c==ADDI2P||c==MULT||c==LSHIFT||c==RSHIFT||c==OR||c==AND)){
  204.                 /*  assoziative Operatoren  */
  205.                     struct IC *n=p->next;
  206.                     if(n&&n->code==c&&(n->q2.flags&KONST)&&n->typf==t&&n->q1.flags==p->z.flags&&n->q1.v==p->z.v&&zleqto(n->q1.val.vlong,p->z.val.vlong)){
  207.                         if(DEBUG&1024){ printf("using associativity with:\n");pric2(stdout,p);pric2(stdout,p->next);}
  208.                         n->q1=p->q1;
  209.                         if(c==LSHIFT||c==RSHIFT||c==ADDI2P)
  210.                             calc(ADD,t,&p->q2.val,&n->q2.val,&n->q2.val);
  211.                         else
  212.                             calc(c,t,&p->q2.val,&n->q2.val,&n->q2.val);
  213.                         changed=1;
  214.                         if(p->q1.flags==p->z.flags&&p->q1.v==p->z.v&&zleqto(p->q1.val.vlong,p->z.val.vlong)){
  215.                             if(DEBUG&1024) printf("must remove first operation\n");
  216.                             n=p;p=p->next;remove_IC(n);continue;
  217.                         }
  218.                     }
  219.                 }
  220.                 if((c==ADDI2P||c==SUBIFP)&&(p->q1.flags&VARADR)){
  221.                 /*  add #var,#const -> move #var+const      */
  222.                     union atyps val;
  223.                     if(DEBUG&1024){printf("add/sub #var,#const changed to assign:\n");pric2(stdout,p);}
  224.                     eval_const(&p->q2.val,t);
  225.                     insert_const2(&val,LONG);
  226.                     if(c==ADDI2P) calc(ADD,LONG,&p->q1.val,&val,&p->q1.val);
  227.                         else      calc(SUB,LONG,&p->q1.val,&val,&p->q1.val);
  228.                     p->code=ASSIGN;
  229.                     p->q2.flags=0;
  230.                     p->q2.reg=sizetab[t&15];
  231.                     changed=1;
  232.                 }
  233.                 if((c==ADD||c==SUB)&&(t&15)<=LONG&&p->next&&p->next->next){
  234.                     struct IC *p1=p->next,*p2=p1->next;
  235.                     if(p1->code==MULT&&p2->code==ADDI2P&&
  236.                        p1->typf==t&&p2->typf==t&&
  237.                        (p1->q2.flags&KONST)&&(p->z.flags&SCRATCH)&&(p1->z.flags&SCRATCH)&&
  238.                        !compare_objs(&p->z,&p1->q1,t)&&
  239.                        !compare_objs(&p1->z,&p2->q2,t)){
  240.                         if(DEBUG&1024){ printf("rearranging array-access:\n");pric2(stdout,p);pric2(stdout,p1);pric2(stdout,p2);}
  241.                         p1->q1=p->q1;
  242.                         p->q1=p2->q1;
  243.                         p2->q1=p2->z;
  244.                         p->z=p2->z;
  245.                         calc(MULT,t,&p->q2.val,&p1->q2.val,&p->q2.val);
  246.                         if(c==ADD) p->code=ADDI2P; else p->code=SUBIFP;
  247.                         changed=1;continue;
  248.                     }
  249.                 }
  250.             }
  251.             if(p->q1.flags&KONST){
  252.             /*  algebraische Optimierungen  */
  253.                 eval_const(&p->q1.val,t);
  254.                 if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)) null=1; else null=0;
  255.                 if(null&&(c==DIV||c==MOD||c==LSHIFT||c==RSHIFT)){
  256.                     if(DEBUG&1024){ printf("operation converted to ASSIGN 0:\n");pric2(stdout,p);}
  257.                     o.val.vlong=l2zl(0L);eval_const(&o.val,LONG);
  258.                     insert_const2(&p->q1.val,t);p->q1.flags=KONST;
  259.                     p->code=ASSIGN;p->q2.flags=0;p->q2.reg=sizetab[t&15];
  260.                     changed=1;
  261.                 }
  262.             }
  263.             if(!USEQ2ASZ&&p->z.flags&&!compare_objs(&p->q2,&p->z,p->typf)){
  264.                 if(c==ADD||c==MULT||(c>=OR&&c<=AND)){
  265.                     struct obj o;
  266.                     if(DEBUG&1024){printf("swapping objs because USEQ2ASZ\n");pric2(stdout,p);}
  267.                     o=p->q2;p->q2=p->q1;p->q1=o;
  268.                     /*  kein changed hier!  */
  269.                 }else{pric2(stdout,p); ierror(0);}
  270.             }
  271.             if((c==ADD||c==SUB)&&p->next){
  272.                 struct IC *p1=p->next;
  273.                 if(p1->code==ADDI2P&&p1->typf==t&&(p->z.flags&SCRATCH)&&!compare_objs(&p->z,&p1->q2,t)){
  274.                     if(DEBUG&1024){ printf("rearranging array-access:\n");pric2(stdout,p);pric2(stdout,p1);}
  275.                     p1->q2=p->q1;
  276.                     p->q1=p1->q1;
  277.                     p->z=p1->z;
  278.                     p1->q1=p1->z;
  279.                     if(c==ADD) p->code=ADDI2P; else p->code=SUBIFP;
  280.                     changed=1;continue;
  281.                 }
  282.             }
  283.             if(c==ASSIGN&&(p->z.flags&VAR)&&p->z.flags==p->q1.flags&&p->z.v==p->q1.v&&zleqto(p->z.val.vlong,p->q1.val.vlong)){
  284.                 struct IC *d;
  285.                 if(DEBUG&1024){ printf("removing redundant move:\n");pric2(stdout,p);}
  286.                 changed=1;
  287.                 d=p; p=p->next; remove_IC(d); continue;
  288.             }
  289.             p=p->next;
  290.         }
  291.         if(changed) done|=changed;
  292.         gchanged|=changed;
  293.     }while(changed);
  294.     return(done);
  295. }
  296. #endif
  297. #define FREEAV free(av_globals);free(av_statics);free(av_drefs);free(av_address);
  298. void optimize(long flags,struct Var *function)
  299. /*  flags:   1=Register, 2=optimize, 4=cse/cp, 8=constant_propagation,  */
  300. /*          16=dead_assignments, 32=global-optimizations                */
  301. /*          64=blockweise Registervergabe                               */
  302. {
  303. #ifndef NO_OPTIMIZER
  304.     struct flowgraph *fg=0;int r,pass=0;
  305.     if(!(c_flags[11]&USEDFLAG)) c_flags_val[11].l=10;
  306.     if(!function) ierror(0);
  307.     norek=nocall=0;
  308.     report_weird_code=1;
  309.     if(!strcmp(function->identifier,"main")){norek=1;nocall=1;}
  310.     /*  falls main() rekursiv aufgerufen werden kann, muss nomain==0 sein   */
  311.  
  312. #else
  313.  
  314.     flags&=1;
  315.  
  316. #endif
  317.     if(flags&2){
  318. #ifndef NO_OPTIMIZER
  319.         /*  nur ein pass, wenn nur lokale Optimierungen */
  320.         if(!(flags&32)) c_flags_val[11].l=1;
  321.         do{
  322.             gchanged=0;pass++;
  323.             av_globals=av_statics=av_address=av_drefs=0;
  324.             rd_globals=rd_statics=rd_address=rd_drefs=0;
  325.             ae_globals=ae_statics=ae_address=ae_drefs=0;
  326.             cp_globals=cp_statics=cp_address=cp_drefs=0;
  327.             dlist=0;vilist=0;elist=0;rd_parms=0;
  328.  
  329.             if(DEBUG&1024) printf("\noptimizer (function %s) pass %d\n",function->identifier,pass);
  330.             num_vars();
  331.             peephole();
  332.             fg=jump_optimization();
  333.             if(DEBUG&2048) print_vi();
  334.             if(flags&8){
  335.                 do{
  336.                     int i;
  337.                     num_defs();
  338.                     if(flags&32){
  339.                         reaching_definitions(fg);
  340.                         if(DEBUG&1024) print_flowgraph(fg);
  341.                     }
  342.                     r=constant_propagation(fg,flags&32);
  343.                     if(DEBUG&1024) {printf("constant_propagation returned %d\n",r);print_flowgraph(fg);}
  344.                     if(r){
  345.                         if(peephole()){free_flowgraph(fg);fg=jump_optimization();}
  346.                     }
  347.                 }while(r);
  348.             }
  349.             if(flags&4){
  350.                 int repeat;
  351.                 do{
  352.                     num_exp();
  353.                     if(DEBUG&1024) print_flowgraph(fg);
  354.                     repeat=r=cse(fg,0);    /*  local cse   */
  355.                     if(DEBUG&1024) printf("local cse returned %d\n",r);
  356.                     gchanged|=r;
  357.                     if(r){  /*  neue Variablen eingefuegt   */
  358.                         if(DEBUG&1024) printf("must repeat num_vars\n");
  359.                         free(vilist);
  360.                         FREEAV;
  361.                         num_vars();
  362.                     }
  363.                     num_copies();
  364.                     if(DEBUG&1024) print_flowgraph(fg);
  365.                     r=copy_propagation(fg,0);   /*  copy propagation    */
  366.                     if(DEBUG&1024) printf("local copy propagation returned %d\n",r);
  367.                     if(r&2){
  368.                         if(DEBUG&1024) printf("must repeat num_vars\n");
  369.                         free(vilist);
  370.                         FREEAV;
  371.                         num_vars();
  372.                     }
  373.                     gchanged|=r;repeat|=r;
  374.                 }while(repeat);
  375.                 if(flags&32){
  376.                     num_exp();
  377.                     if(DEBUG&1024) print_flowgraph(fg);
  378.                     available_expressions(fg);
  379.                     r=cse(fg,1);gchanged|=r;
  380.                     if(DEBUG&1024) printf("global cse returned %d\n",r);
  381.                     if(r){  /*  neue Variablen eingefuegt   */
  382.                         if(DEBUG&1024) printf("must repeat num_vars\n");
  383.                         free(vilist);
  384.                         FREEAV;
  385.                         num_vars();
  386.                         gchanged|=r;
  387.                         do{
  388.                             num_copies();
  389.                             if(DEBUG&1024) print_flowgraph(fg);
  390.                             r=copy_propagation(fg,0);   /*  copy propagation    */
  391.                             if(DEBUG&1024) printf("local copy propagation returned %d\n",r);
  392.                             if(r&2){
  393.                                 if(DEBUG&1024) printf("must repeat num_vars\n");
  394.                                 free(vilist);
  395.                                 FREEAV;
  396.                                 num_vars();
  397.                             }
  398.                             gchanged|=r;
  399.                         }while(r);
  400.                     }
  401.                     num_copies();
  402.                     if(DEBUG&1024) print_flowgraph(fg);
  403.                     available_copies(fg);
  404.                     r=copy_propagation(fg,1);   /*  copy propagation    */
  405.                     if(DEBUG&1024) printf("global copy propagation returned %d\n",r);
  406.                     if(r&2){
  407.                         if(DEBUG&1024) printf("must repeat num_vars\n");
  408.                         free(vilist);
  409.                         FREEAV;
  410.                         num_vars();
  411.                     }
  412.                     gchanged|=r;
  413.                 }
  414.             }
  415.             if((flags&16)||((flags&1)&&pass>=c_flags_val[11].l)){
  416. /*                num_vars();*/
  417.                 active_vars(fg);
  418.                 if(DEBUG&1024) print_flowgraph(fg);
  419.                 if((flags&16)&&pass<=c_flags_val[11].l){
  420.                     r=dead_assignments(fg);
  421.                     if(DEBUG&1024) printf("dead_assignments returned %d\n",r);
  422.                     gchanged|=r;
  423.                 }
  424.             }
  425.  
  426.  
  427.             if((!gchanged||pass>=c_flags_val[11].l)){
  428.             /*  Funktion evtl. fuer inlining vorbereiten und    */
  429.             /*  Registervergabe                                 */
  430.  
  431.                 /*  default-Wert fuer inline-Entscheidung   */
  432.                 if(!(c_flags[12]&USEDFLAG)) c_flags_val[12].l=30;
  433.                 if((c_flags[0]&USEDFLAG)&&(c_flags_val[0].l&4096)&&(only_inline||ic_count<=c_flags_val[12].l)){
  434.                 /*  fuer function inlinig vorbereiten   */
  435.                     struct IC *p,*new;
  436.                     if(DEBUG&1024) printf("function <%s> prepared for inlining(ic_count=%d)\n",function->identifier,ic_count);
  437.                     function->fi=mymalloc(sizeof(struct function_info));
  438.                     function->fi->first_ic=first_ic;
  439.                     function->fi->last_ic=last_ic;
  440.                     first_ic=last_ic=0;
  441.                     p=function->fi->first_ic;
  442.                     while(p){
  443.                         new=mymalloc(ICS);
  444.                         memcpy(new,p,ICS);
  445.                         if((p->code>=BEQ&&p->code<=BRA)||p->code==LABEL)
  446.                             new->typf-=lastlabel;
  447.                         add_IC(new);
  448.                         p=p->next;
  449.                     }
  450.                     p=first_ic;first_ic=function->fi->first_ic;function->fi->first_ic=p;
  451.                     p=last_ic;last_ic=function->fi->last_ic;function->fi->last_ic=p;
  452.                     function->fi->vars=0;
  453.                 }
  454.                 if(flags&1){
  455.                     local_regs(fg);
  456.                     loops(fg,1);
  457.                     if(DEBUG&1024) print_flowgraph(fg);
  458.                     fg=create_loop_headers(fg);
  459.                     if(DEBUG&1024) print_flowgraph(fg);
  460.                     fg=create_loop_footers(fg);
  461.                     if(DEBUG&1024) print_flowgraph(fg);
  462.                     loop_regs(fg);
  463.                     if(DEBUG&1024) print_flowgraph(fg);
  464.                     if(flags&64){
  465.                         block_regs(fg);
  466.                         if(DEBUG&1024) print_flowgraph(fg);
  467.                     }
  468.                     insert_regs(fg);
  469.                 }
  470.                 if(flags&128) recalc_offsets(fg);
  471.             }
  472.  
  473.             free_flowgraph(fg);
  474.             free(vilist);
  475.             FREEAV;
  476.  
  477.             if((flags&32)&&gchanged&&pass>=c_flags_val[11].l) error(172,c_flags_val[11].l);
  478.  
  479.         }while(gchanged&&pass<c_flags_val[11].l);
  480.  
  481.         /*  nur, um nochmal ueberfluessige Labels zu entfernen  */
  482.         fg=construct_flowgraph();
  483.         free_flowgraph(fg);
  484.  
  485.         /*  Register bei Funktionsaufrufen sichern  */
  486.         insert_saves();
  487.  
  488. #endif
  489.  
  490.     }else{
  491.         /*  keine Optimierungen     */
  492.         if(flags&1) simple_regs();
  493.     }
  494.     lastlabel=label;
  495. }
  496.  
  497.